﻿#pragma once
//#include <iostream>
//#include <vector>
//#include <time.h>
//#include <Windows.h>
//#include "Common.h"
#include <mutex>
using std::cout;
using std::endl;
//定长内存池
// 直接去堆上按⻚申请空间
//inline static void* SystemAlloc(size_t kpage)
//{
//#ifdef _WIN32
//		void* ptr = VirtualAlloc(0, kpage * (1 << 12), MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);
//#else
//		// linux下brk mmap等
//#endif
//		if (ptr == nullptr)
//			throw std::bad_alloc();
//	return ptr;
//}
template<class T>
class ObjectPool
{
public:
	T* New()
	{
		T* obj = nullptr;
		{
			std::unique_lock<std::mutex> lock(_mtx);
		
			
			// 如果⾃由链表有对象，直接取⼀个
			//优先把还回来内存块对象，再次重复使用
			if (_freeList)  //如果链表不为空，freelist的前四个字节（8个）存放下一个节点的位置
			{
				/*obj = (t*)_freelist;
				_freelist = *((void**)_freelist);*/
				void* next = *((void**)_freeList);
				obj = (T*)_freeList;
				_freeList = next;
			
			}
			else
			{
				if (_leftBytes<sizeof(T))
				{
					_leftBytes = 128 * 1024;
					_memory = (char*)malloc(_leftBytes);
					if (_memory == nullptr)
					{
						throw std::bad_alloc();
					}
				}
				obj = (T*)_memory;//指向大块内存的开始
				size_t objsize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T); 
				_memory += objsize;	//分配一块内存后，指针向后移动
				_leftBytes -= objsize; //可分配内存减小
			}
			// 使⽤定位new调⽤T的构造函数初始化
		}
		new(obj)T ;
		return obj;
		
	}
	void Delete(T* obj)
	{
		std::unique_lock<std::mutex> lock(_mtx);
		obj->~T();// 显⽰调⽤的T的析构函数进⾏清理
		//头插
		*((void**)obj) = _freeList; //_freelist就是空闲链表的头指针，表示当前空闲的内存块链表；obj被插入空闲链表的头部
		_freeList = obj; //更新_freelist的指向位置，
		//举例子说，_freeList原来下一个是指向NULL  freeList->NULL，现在存入obj的前四/八字节，obj的下一个为空  obj->NULL
		//更新_freeList指向位置为obj，就实现了  freelist->obj->NULL
	}

private:
	char* _memory=nullptr; //指向内存块的指针
	void* _freeList = nullptr;	//管理还回来的内存对象的自由链表
	int _leftBytes = 0;	//内存块剩下的字节数
	std::mutex _mtx;
};
//struct TreeNode
//{
//	int _val;
//	TreeNode* _left;
//	TreeNode* _right;
//	TreeNode()
//		:_val(0)
//		, _left(nullptr)
//		, _right(nullptr)
//	{}
//};
//
//inline void TestObjectPool()
//{
//	// 申请释放的轮次
//	const size_t Rounds = 3;
//	// 每轮申请释放多少次
//	const size_t N = 100000;
//	size_t begin1 = clock();
//	std::vector<TreeNode*> v1;
//	v1.reserve(N);
//	for (size_t j = 0; j < Rounds; ++j)
//	{
//		for (int i = 0; i < N; ++i)
//		{
//		v1.push_back(new TreeNode);
//		}
//		for (int i = 0; i < N; ++i)
//		{
//		delete v1[i];
//		}
//		v1.clear();
//	}
//	size_t end1 = clock();
//	ObjectPool<TreeNode> TNPool;
//	size_t begin2 = clock();
//	std::vector<TreeNode*> v2;
//	v2.reserve(N);
//	for (size_t j = 0; j < Rounds; ++j)
//	{
//		for (int i = 0; i < N; ++i)
//		{
//			v2.push_back(TNPool.New());
//		}
//		for (int i = 0; i < 100000; ++i)
//		{
//			TNPool.Delete(v2[i]);
//		}
//		v2.clear();
//	}
//	size_t end2 = clock();
//	cout << "new cost time:" << end1 - begin1 << endl;
//	cout << "object pool cost time:" << end2 - begin2 << endl;
//}